/*
 * Copyright (c) 2010 Vadim Zhukov <persgray@gmail.com>
 *
 * Permission to use, copy, modify, and distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */


#include "common.h"


#include <errno.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "peertask.h"
#include "logmsg.h"


/*
 * NOTE: Routines here assume that "producer" and "text" fields of log_msg
 * structure are either NULL or malloc()'ed ones, and act as owners.
 */

struct log_msg *
log_msg_new(struct log_msg *prev) {
	struct log_msg	*m;

	m = malloc(sizeof(struct log_msg));
	if (m == NULL)
		goto err;
	bzero(m, sizeof(struct log_msg));
	m->hdr = malloc(sizeof(struct log_msg_hdr));
	if (m->hdr == NULL)
		goto err;
	bzero(m->hdr, sizeof(struct log_msg_hdr));
	if (prev != NULL)
		prev->next = m;
	return m;

err:
	free(m);
	return NULL;
}

/*
 * Used in error cases or when log line become filtered out.
 */
void
log_msg_free(struct log_msg *m) {
	struct log_msg	*m2;

	for (; m != NULL; m = m2) {
		m2 = m->next;
		free(m->hdr);
		free(m->producer);
		free(m->text);
		free(m->source);
		free(m);
	}
}

/*
 * Convert log_msg structure to a peer_task structure.
 */
struct peer_task *
log_msg_to_peer_task(struct log_msg *m) {
	struct peer_task	*task;
	struct peer_data_buffer	*buf;
	size_t			 len;
	int			 oerrno;

	task = peer_new_task(1, NULL);
	if (task == NULL)
		goto err;
	peer_init_task(task, PEER_CMD_LINE);
	buf = peer_new_data_buffer(sizeof(struct log_msg_hdr), m->hdr);
	if (buf == NULL)
		goto err;
	peer_add_task_data(task, buf, -1);

	len = strlen(m->producer);
	buf = peer_new_data_buffer(len, m->producer);
	if (buf == NULL)
		goto err;
	peer_add_task_data(task, buf, -1);

	len = strlen(m->text);
	buf = peer_new_data_buffer(len, m->text);
	if (buf == NULL)
		goto err;
	peer_add_task_data(task, buf, -1);

	if (m->source != NULL) {
		len = strlen(m->source);
		buf = peer_new_data_buffer(len, m->source);
		if (buf == NULL)
			goto err;
		peer_add_task_data(task, buf, -1);
	}
	return task;

err:
	oerrno = errno;
	if (task != NULL)
		peer_free_task(task, 1);
	errno = oerrno;
	return NULL;
}
